home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / usr / lib / python2.4 / mimify.pyc (.txt) < prev    next >
Python Compiled Bytecode  |  2005-10-18  |  12KB  |  501 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.4)
  3.  
  4. '''Mimification and unmimification of mail messages.
  5.  
  6. Decode quoted-printable parts of a mail message or encode using
  7. quoted-printable.
  8.  
  9. Usage:
  10.         mimify(input, output)
  11.         unmimify(input, output, decode_base64 = 0)
  12. to encode and decode respectively.  Input and output may be the name
  13. of a file or an open file object.  Only a readline() method is used
  14. on the input file, only a write() method is used on the output file.
  15. When using file names, the input and output file names may be the
  16. same.
  17.  
  18. Interactive usage:
  19.         mimify.py -e [infile [outfile]]
  20.         mimify.py -d [infile [outfile]]
  21. to encode and decode respectively.  Infile defaults to standard
  22. input and outfile to standard output.
  23. '''
  24. MAXLEN = 200
  25. CHARSET = 'ISO-8859-1'
  26. QUOTE = '> '
  27. import re
  28. __all__ = [
  29.     'mimify',
  30.     'unmimify',
  31.     'mime_encode_header',
  32.     'mime_decode_header']
  33. qp = re.compile('^content-transfer-encoding:\\s*quoted-printable', re.I)
  34. base64_re = re.compile('^content-transfer-encoding:\\s*base64', re.I)
  35. mp = re.compile('^content-type:.*multipart/.*boundary="?([^;"\n]*)', re.I | re.S)
  36. chrset = re.compile('^(content-type:.*charset=")(us-ascii|iso-8859-[0-9]+)(".*)', re.I | re.S)
  37. he = re.compile('^-*\n')
  38. mime_code = re.compile('=([0-9a-f][0-9a-f])', re.I)
  39. mime_head = re.compile('=\\?iso-8859-1\\?q\\?([^? \t\n]+)\\?=', re.I)
  40. repl = re.compile('^subject:\\s+re: ', re.I)
  41.  
  42. class File:
  43.     '''A simple fake file object that knows about limited read-ahead and
  44.     boundaries.  The only supported method is readline().'''
  45.     
  46.     def __init__(self, file, boundary):
  47.         self.file = file
  48.         self.boundary = boundary
  49.         self.peek = None
  50.  
  51.     
  52.     def readline(self):
  53.         if self.peek is not None:
  54.             return ''
  55.         
  56.         line = self.file.readline()
  57.         if not line:
  58.             return line
  59.         
  60.         if self.boundary:
  61.             if line == self.boundary + '\n':
  62.                 self.peek = line
  63.                 return ''
  64.             
  65.             if line == self.boundary + '--\n':
  66.                 self.peek = line
  67.                 return ''
  68.             
  69.         
  70.         return line
  71.  
  72.  
  73.  
  74. class HeaderFile:
  75.     
  76.     def __init__(self, file):
  77.         self.file = file
  78.         self.peek = None
  79.  
  80.     
  81.     def readline(self):
  82.         if self.peek is not None:
  83.             line = self.peek
  84.             self.peek = None
  85.         else:
  86.             line = self.file.readline()
  87.         if not line:
  88.             return line
  89.         
  90.         if he.match(line):
  91.             return line
  92.         
  93.         while None:
  94.             self.peek = self.file.readline()
  95.             if (len(self.peek) == 0 or self.peek[0] != ' ') and self.peek[0] != '\t':
  96.                 return line
  97.             
  98.             line = line + self.peek
  99.             self.peek = None
  100.  
  101.  
  102.  
  103. def mime_decode(line):
  104.     '''Decode a single line of quoted-printable text to 8bit.'''
  105.     newline = ''
  106.     pos = 0
  107.     while None:
  108.         res = mime_code.search(line, pos)
  109.         if res is None:
  110.             break
  111.         
  112.         newline = newline + line[pos:res.start(0)] + chr(int(res.group(1), 16))
  113.         pos = res.end(0)
  114.     return newline + line[pos:]
  115.  
  116.  
  117. def mime_decode_header(line):
  118.     '''Decode a header line to 8bit.'''
  119.     newline = ''
  120.     pos = 0
  121.     while None:
  122.         res = mime_head.search(line, pos)
  123.         if res is None:
  124.             break
  125.         
  126.         match = res.group(1)
  127.         match = ' '.join(match.split('_'))
  128.         newline = newline + line[pos:res.start(0)] + mime_decode(match)
  129.         pos = res.end(0)
  130.     return newline + line[pos:]
  131.  
  132.  
  133. def unmimify_part(ifile, ofile, decode_base64 = 0):
  134.     '''Convert a quoted-printable part of a MIME mail message to 8bit.'''
  135.     multipart = None
  136.     quoted_printable = 0
  137.     is_base64 = 0
  138.     is_repl = 0
  139.     if ifile.boundary and ifile.boundary[:2] == QUOTE:
  140.         prefix = QUOTE
  141.     else:
  142.         prefix = ''
  143.     hfile = HeaderFile(ifile)
  144.     while None:
  145.         line = hfile.readline()
  146.         if not line:
  147.             return None
  148.         
  149.         if prefix and line[:len(prefix)] == prefix:
  150.             line = line[len(prefix):]
  151.             pref = prefix
  152.         else:
  153.             pref = ''
  154.         line = mime_decode_header(line)
  155.         if qp.match(line):
  156.             quoted_printable = 1
  157.             continue
  158.         
  159.         if decode_base64 and base64_re.match(line):
  160.             is_base64 = 1
  161.             continue
  162.         
  163.         if not prefix and repl.match(line):
  164.             is_repl = 1
  165.         
  166.         mp_res = mp.match(line)
  167.         if mp_res:
  168.             multipart = '--' + mp_res.group(1)
  169.         
  170.         if he.match(line):
  171.             break
  172.             continue
  173.     if is_repl:
  174.         if quoted_printable or multipart:
  175.             is_repl = 0
  176.         
  177.     while None:
  178.         line = ifile.readline()
  179.         if not line:
  180.             return None
  181.         
  182.         line = re.sub(mime_head, '\\1', line)
  183.         if prefix and line[:len(prefix)] == prefix:
  184.             line = line[len(prefix):]
  185.             pref = prefix
  186.         else:
  187.             pref = ''
  188.         while multipart:
  189.             if line == multipart + '--\n':
  190.                 ofile.write(pref + line)
  191.                 multipart = None
  192.                 line = None
  193.                 break
  194.             
  195.             if line == multipart + '\n':
  196.                 ofile.write(pref + line)
  197.                 nifile = File(ifile, multipart)
  198.                 unmimify_part(nifile, ofile, decode_base64)
  199.                 line = nifile.peek
  200.                 if not line:
  201.                     break
  202.                     continue
  203.                 continue
  204.             
  205.             break
  206.         if line and quoted_printable:
  207.             while line[-2:] == '=\n':
  208.                 line = line[:-2]
  209.                 newline = ifile.readline()
  210.                 if newline[:len(QUOTE)] == QUOTE:
  211.                     newline = newline[len(QUOTE):]
  212.                 
  213.                 line = line + newline
  214.             line = mime_decode(line)
  215.         
  216.         if line and is_base64 and not pref:
  217.             import base64 as base64
  218.             line = base64.decodestring(line)
  219.         
  220.         if line:
  221.             ofile.write(pref + line)
  222.             continue
  223.  
  224.  
  225. def unmimify(infile, outfile, decode_base64 = 0):
  226.     '''Convert quoted-printable parts of a MIME mail message to 8bit.'''
  227.     if type(infile) == type(''):
  228.         ifile = open(infile)
  229.         if type(outfile) == type('') and infile == outfile:
  230.             import os as os
  231.             (d, f) = os.path.split(infile)
  232.             os.rename(infile, os.path.join(d, ',' + f))
  233.         
  234.     else:
  235.         ifile = infile
  236.     if type(outfile) == type(''):
  237.         ofile = open(outfile, 'w')
  238.     else:
  239.         ofile = outfile
  240.     nifile = File(ifile, None)
  241.     unmimify_part(nifile, ofile, decode_base64)
  242.     ofile.flush()
  243.  
  244. mime_char = re.compile('[=\x7f-\xff]')
  245. mime_header_char = re.compile('[=?\x7f-\xff]')
  246.  
  247. def mime_encode(line, header):
  248.     '''Code a single line as quoted-printable.
  249.     If header is set, quote some extra characters.'''
  250.     if header:
  251.         reg = mime_header_char
  252.     else:
  253.         reg = mime_char
  254.     newline = ''
  255.     pos = 0
  256.     if len(line) >= 5 and line[:5] == 'From ':
  257.         newline = ('=%02x' % ord('F')).upper()
  258.         pos = 1
  259.     
  260.     while None:
  261.         res = reg.search(line, pos)
  262.         if res is None:
  263.             break
  264.         
  265.         newline = newline + line[pos:res.start(0)] + ('=%02x' % ord(res.group(0))).upper()
  266.         pos = res.end(0)
  267.     line = newline + line[pos:]
  268.     newline = ''
  269.     while len(line) >= 75:
  270.         i = 73
  271.         while line[i] == '=' or line[i - 1] == '=':
  272.             i = i - 1
  273.         i = i + 1
  274.         newline = newline + line[:i] + '=\n'
  275.         line = line[i:]
  276.     return newline + line
  277.  
  278. mime_header = re.compile('([ \t(]|^)([-a-zA-Z0-9_+]*[\x7f-\xff][-a-zA-Z0-9_+\x7f-\xff]*)(?=[ \t)]|\n)')
  279.  
  280. def mime_encode_header(line):
  281.     '''Code a single header line as quoted-printable.'''
  282.     newline = ''
  283.     pos = 0
  284.     while None:
  285.         res = mime_header.search(line, pos)
  286.         if res is None:
  287.             break
  288.         
  289.         newline = '%s%s%s=?%s?Q?%s?=' % (newline, line[pos:res.start(0)], res.group(1), CHARSET, mime_encode(res.group(2), 1))
  290.         pos = res.end(0)
  291.     return newline + line[pos:]
  292.  
  293. mv = re.compile('^mime-version:', re.I)
  294. cte = re.compile('^content-transfer-encoding:', re.I)
  295. iso_char = re.compile('[\x7f-\xff]')
  296.  
  297. def mimify_part(ifile, ofile, is_mime):
  298.     '''Convert an 8bit part of a MIME mail message to quoted-printable.'''
  299.     has_cte = is_qp = is_base64 = 0
  300.     multipart = None
  301.     must_quote_body = must_quote_header = has_iso_chars = 0
  302.     header = []
  303.     header_end = ''
  304.     message = []
  305.     message_end = ''
  306.     hfile = HeaderFile(ifile)
  307.     while None:
  308.         line = hfile.readline()
  309.         if not line:
  310.             break
  311.         
  312.         if not must_quote_header and iso_char.search(line):
  313.             must_quote_header = 1
  314.         
  315.         if mv.match(line):
  316.             is_mime = 1
  317.         
  318.         if cte.match(line):
  319.             has_cte = 1
  320.             if qp.match(line):
  321.                 is_qp = 1
  322.             elif base64_re.match(line):
  323.                 is_base64 = 1
  324.             
  325.         
  326.         mp_res = mp.match(line)
  327.         if mp_res:
  328.             multipart = '--' + mp_res.group(1)
  329.         
  330.         if he.match(line):
  331.             header_end = line
  332.             break
  333.         
  334.     while None:
  335.         line = ifile.readline()
  336.         if not line:
  337.             break
  338.         
  339.         if multipart:
  340.             if line == multipart + '--\n':
  341.                 message_end = line
  342.                 break
  343.             
  344.             if line == multipart + '\n':
  345.                 message_end = line
  346.                 break
  347.             
  348.         
  349.         if is_base64:
  350.             message.append(line)
  351.             continue
  352.         
  353.         if is_qp:
  354.             while line[-2:] == '=\n':
  355.                 line = line[:-2]
  356.                 newline = ifile.readline()
  357.                 if newline[:len(QUOTE)] == QUOTE:
  358.                     newline = newline[len(QUOTE):]
  359.                 
  360.                 line = line + newline
  361.             line = mime_decode(line)
  362.         
  363.         if not has_iso_chars:
  364.             if iso_char.search(line):
  365.                 has_iso_chars = must_quote_body = 1
  366.             
  367.         
  368.         if not must_quote_body:
  369.             if len(line) > MAXLEN:
  370.                 must_quote_body = 1
  371.             
  372.         len(line) > MAXLEN
  373.     for line in header:
  374.         if must_quote_header:
  375.             line = mime_encode_header(line)
  376.         
  377.         chrset_res = chrset.match(line)
  378.         if chrset_res:
  379.             if has_iso_chars:
  380.                 if chrset_res.group(2).lower() == 'us-ascii':
  381.                     line = '%s%s%s' % (chrset_res.group(1), CHARSET, chrset_res.group(3))
  382.                 
  383.             else:
  384.                 line = '%sus-ascii%s' % chrset_res.group(1, 3)
  385.         
  386.         if has_cte and cte.match(line):
  387.             line = 'Content-Transfer-Encoding: '
  388.             if is_base64:
  389.                 line = line + 'base64\n'
  390.             elif must_quote_body:
  391.                 line = line + 'quoted-printable\n'
  392.             else:
  393.                 line = line + '7bit\n'
  394.         
  395.         ofile.write(line)
  396.     
  397.     if (must_quote_header or must_quote_body) and not is_mime:
  398.         ofile.write('Mime-Version: 1.0\n')
  399.         ofile.write('Content-Type: text/plain; ')
  400.         if has_iso_chars:
  401.             ofile.write('charset="%s"\n' % CHARSET)
  402.         else:
  403.             ofile.write('charset="us-ascii"\n')
  404.     
  405.     if must_quote_body and not has_cte:
  406.         ofile.write('Content-Transfer-Encoding: quoted-printable\n')
  407.     
  408.     ofile.write(header_end)
  409.     for line in message:
  410.         if must_quote_body:
  411.             line = mime_encode(line, 0)
  412.         
  413.         ofile.write(line)
  414.     
  415.     ofile.write(message_end)
  416.     line = message_end
  417.     while multipart:
  418.         if line == multipart + '--\n':
  419.             while None:
  420.                 line = ifile.readline()
  421.                 if not line:
  422.                     return None
  423.                 
  424.                 if must_quote_body:
  425.                     line = mime_encode(line, 0)
  426.                 
  427.         
  428.         if line == multipart + '\n':
  429.             nifile = File(ifile, multipart)
  430.             mimify_part(nifile, ofile, 1)
  431.             line = nifile.peek
  432.             if not line:
  433.                 break
  434.             
  435.             ofile.write(line)
  436.             continue
  437.         
  438.         while None:
  439.             line = ifile.readline()
  440.             if not line:
  441.                 return None
  442.             
  443.             if must_quote_body:
  444.                 line = mime_encode(line, 0)
  445.             
  446.  
  447.  
  448. def mimify(infile, outfile):
  449.     '''Convert 8bit parts of a MIME mail message to quoted-printable.'''
  450.     if type(infile) == type(''):
  451.         ifile = open(infile)
  452.         if type(outfile) == type('') and infile == outfile:
  453.             import os
  454.             (d, f) = os.path.split(infile)
  455.             os.rename(infile, os.path.join(d, ',' + f))
  456.         
  457.     else:
  458.         ifile = infile
  459.     if type(outfile) == type(''):
  460.         ofile = open(outfile, 'w')
  461.     else:
  462.         ofile = outfile
  463.     nifile = File(ifile, None)
  464.     mimify_part(nifile, ofile, 0)
  465.     ofile.flush()
  466.  
  467. import sys
  468. if (__name__ == '__main__' or len(sys.argv) > 0) and sys.argv[0] == 'mimify':
  469.     import getopt
  470.     usage = 'Usage: mimify [-l len] -[ed] [infile [outfile]]'
  471.     decode_base64 = 0
  472.     (opts, args) = getopt.getopt(sys.argv[1:], 'l:edb')
  473.     if len(args) not in (0, 1, 2):
  474.         print usage
  475.         sys.exit(1)
  476.     
  477.     if ((('-e', '') in opts) == (('-d', '') in opts) or ('-b', '') in opts) and ('-d', '') not in opts:
  478.         print usage
  479.         sys.exit(1)
  480.     
  481.     for o, a in opts:
  482.         if o == '-e':
  483.             encode = mimify
  484.             continue
  485.         None if o == '-d' else None<EXCEPTION MATCH>(ValueError, OverflowError)
  486.         if o == '-b':
  487.             decode_base64 = 1
  488.             continue
  489.     
  490.     if len(args) == 0:
  491.         encode_args = (sys.stdin, sys.stdout)
  492.     elif len(args) == 1:
  493.         encode_args = (args[0], sys.stdout)
  494.     else:
  495.         encode_args = (args[0], args[1])
  496.     if decode_base64:
  497.         encode_args = encode_args + (decode_base64,)
  498.     
  499.     encode(*encode_args)
  500.  
  501.